package com.myFwk.service;

import com.myFwk.constant.LoginConstant;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.support.CustomSQLExceptionTranslatorRegistrar;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCrypt;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.HttpRequestHandlerServlet;
import org.springframework.web.servlet.support.RequestContext;

import javax.annotation.Resource;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Title:
 * @Description:
 * @Author: guowl
 * @version： 1.0
 * @Date:2021/8/27
 * @Copyright: Copyright(c)2021 RedaFlight.com All Rights Reserved
 */
@Service
public class UserDetilServiceImpl implements UserDetailsService {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        String loginType = attributes.getRequest().getParameter("login_type");
        if (StringUtils.isEmpty(loginType)) {
            throw new AuthenticationServiceException("登录类型不能为空！");
        }
        String refreshType = attributes.getRequest().getParameter("grant_type");
        if (LoginConstant.REFRESH_TOKEN.equalsIgnoreCase(refreshType)) {
            username = adjustUserName(username, loginType);
        }
        //获取请求的参数，根据登录类型来选择登录方式
        UserDetails userDetails = null;
        try {
            switch (loginType) {
                //管理员登录方式
                case LoginConstant.ADMIN_TYPE:
                    userDetails = loadAdminUserByUsername(username);
                    break;
                //会员登录方式
                case LoginConstant.MEMBER_TYPE:
                    userDetails = loadMemberUserByUsername(username);
                    break;
                default:
                    throw new AuthenticationServiceException("暂未支持其他类型登录！" + loginType);
            }
        } catch (IncorrectResultSizeDataAccessException e) {
            throw new UsernameNotFoundException("用户名未能查询到：" + username);

        }
        return userDetails;
    }

    private String adjustUserName(String id, String loginType) {
        //管理员username 赋值操作
        String username = null;
        if (LoginConstant.ADMIN_TYPE.equalsIgnoreCase(loginType)) {
            username = jdbcTemplate.queryForObject(LoginConstant.QUERY_USER_ID_SQL, String.class, id);
            return username;
        } else {
            //普通用户username 赋值操作
            username = jdbcTemplate.queryForObject(LoginConstant.QUERY_USER_ID_SQL, String.class, id);
            return username;
        }
    }

    private UserDetails loadMemberUserByUsername(String username) {
        return jdbcTemplate.queryForObject(LoginConstant.QUERY_MEMBER_SQL, (rs, rowNum) -> {
            if (rs.wasNull()) {
                throw new UsernameNotFoundException("该用户不存在！" + username);
            }
            long id = rs.getLong("id");
            String password = rs.getString("password");
            int status = rs.getInt("status");
            User user = new User(String.valueOf(id), password, status == 0, true, true, true, Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")));
            return user;
        }, username, username);

    }

    private UserDetails loadAdminUserByUsername(String username) {

        return jdbcTemplate.queryForObject(LoginConstant.QUERY_ADMIN_SQL, new RowMapper<User>() {
            @Override
            public User mapRow(ResultSet rs, int rowNum) throws SQLException {
                if (rs.wasNull()) {
                    throw new UsernameNotFoundException("用户：" + username + "未能查询到！");
                }
                long id = rs.getLong("id");
                String password = rs.getString("password");
                int status = rs.getInt("status");
                //使用用户ID代替用户姓名
                User user = new User(String.valueOf(id), password, status == 1, true, true, true, getUserPermission(id));
                return user;
            }
        }, username);
    }

    private Collection<? extends GrantedAuthority> getUserPermission(long id) {
        //当用户为超级管理员时
        //普通用户需要使用角色 权限数据
        String s = jdbcTemplate.queryForObject(LoginConstant.QUERY_ROLE_CODE_SQL, String.class, id);
        if (s.isEmpty()) {
            return null;
        }
        List<String> permissions = null;
        if (LoginConstant.ADMIN_CODE.equals(s)) {
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_ALL_PERMISSIONS, String.class);
        } else {
            permissions = jdbcTemplate.queryForList(LoginConstant.QUERY_PERMISSION_SQL, String.class, id);
        }
        if (permissions == null || permissions.isEmpty()) {
            return Collections.EMPTY_SET;
        }
        return permissions.stream().distinct().map(perm -> new SimpleGrantedAuthority(perm)).collect(Collectors.toSet());
    }

    /**
     * 密码加密
     *
     * @return
     */
    public static void main(String[] args) {
        PasswordEncoder passwordEncoder=new BCryptPasswordEncoder();
//        String encode = passwordEncoder.encode("123456");
//        System.out.println(encode);
//        String hashpw1 = BCrypt.hashpw("123456", BCrypt.gensalt());
//        System.out.println(hashpw1);
        String encode = passwordEncoder.encode("456789");
        System.out.println(encode);

        boolean checkpw = BCrypt.checkpw("456789", "$2a$10$XHMBkhAY8f3Hwz5jLnm1g.mMFq2gPqV9flhgt.3vxDdOxlf9xIa4C");
        System.out.println(checkpw);
    }
}
